package org.eiahe.hr.salary.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.domain.vo.SysDeptVo;
import org.ehe.system.service.ISysDeptService;
import org.eiahe.hr.filler.EmployeeNameFiller;
import org.eiahe.hr.salary.domain.SalaryAdjustmentApplication;
import org.eiahe.hr.salary.domain.SalaryStructure;
import org.eiahe.hr.salary.domain.bo.SalaryAdjustmentApplicationBo;
import org.eiahe.hr.salary.domain.vo.SalaryAdjustmentApplicationVo;
import org.eiahe.hr.salary.mapper.SalaryAdjustmentApplicationMapper;
import org.eiahe.hr.salary.mapper.SalaryStructureMapper;
import org.eiahe.hr.salary.service.ISalaryAdjustmentApplicationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 调薪申请Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SalaryAdjustmentApplicationServiceImpl implements ISalaryAdjustmentApplicationService {

    private final SalaryAdjustmentApplicationMapper baseMapper;
    private final SalaryStructureMapper salaryStructureMapper;
    private final EmployeeNameFiller employeeNameFiller;

    @Override
    public SalaryAdjustmentApplicationVo queryById(Long applicationId) {
        SalaryAdjustmentApplicationVo vo = baseMapper.selectVoById(applicationId);
        employeeNameFiller.fillEmployeeName(vo,
            SalaryAdjustmentApplicationVo::getEmployeeNo,
            SalaryAdjustmentApplicationVo::setEmployeeName);
        return vo;
    }

    @Override
    public List<SalaryAdjustmentApplicationVo> queryList(SalaryAdjustmentApplicationBo bo) {
        LambdaQueryWrapper<SalaryAdjustmentApplication> lqw = buildQueryWrapper(bo);
        List<SalaryAdjustmentApplicationVo> salaryAdjustmentApplicationVos = baseMapper.selectVoList(lqw);
        employeeNameFiller.fillEmployeeNames(salaryAdjustmentApplicationVos,
            SalaryAdjustmentApplicationVo::getEmployeeNo,
            SalaryAdjustmentApplicationVo::setEmployeeName);
        return salaryAdjustmentApplicationVos;
    }

    @Override
    public TableDataInfo<SalaryAdjustmentApplicationVo> queryPageList(SalaryAdjustmentApplicationBo bo,
            PageQuery pageQuery) {
        LambdaQueryWrapper<SalaryAdjustmentApplication> lqw = buildQueryWrapper(bo);
        IPage<SalaryAdjustmentApplicationVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
        employeeNameFiller.fillEmployeeNames(page.getRecords(),
            SalaryAdjustmentApplicationVo::getEmployeeNo,
            SalaryAdjustmentApplicationVo::setEmployeeName);
        return TableDataInfo.build(page);
    }

    /**
     * 构建查询条件
     *
     * @param bo 调薪申请业务对象
     * @return 查询条件
     */
    private LambdaQueryWrapper<SalaryAdjustmentApplication> buildQueryWrapper(SalaryAdjustmentApplicationBo bo) {
        LambdaQueryWrapper<SalaryAdjustmentApplication> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeNo()), SalaryAdjustmentApplication::getEmployeeNo,
                bo.getEmployeeNo());
        lqw.eq(StringUtils.isNotBlank(bo.getApprovalStatus()), SalaryAdjustmentApplication::getApprovalStatus,
                bo.getApprovalStatus());
        lqw.orderByDesc(SalaryAdjustmentApplication::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean insertByBo(SalaryAdjustmentApplicationBo bo) {
        SalaryAdjustmentApplication add = MapstructUtils.convert(bo, SalaryAdjustmentApplication.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setApplicationId(add.getApplicationId());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(SalaryAdjustmentApplicationBo bo) {
        SalaryAdjustmentApplication update = MapstructUtils.convert(bo, SalaryAdjustmentApplication.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(SalaryAdjustmentApplication entity) {
        // 校验员工工号是否存在
        if (StringUtils.isBlank(entity.getEmployeeNo())) {
            throw new RuntimeException("员工工号不能为空");
        }

        // 校验原薪资和新薪资
        if (entity.getOriginalSalary() == null || entity.getOriginalSalary().compareTo(BigDecimal.ZERO) < 0) {
            throw new RuntimeException("原薪资必须大于等于0");
        }

        if (entity.getNewSalary() == null || entity.getNewSalary().compareTo(BigDecimal.ZERO) < 0) {
            throw new RuntimeException("新薪资必须大于等于0");
        }

        // 校验调薪原因
        if (StringUtils.isBlank(entity.getAdjustmentReason())) {
            throw new RuntimeException("调薪原因不能为空");
        }

        // 校验生效时间
        if (entity.getEffectiveTime() == null) {
            throw new RuntimeException("生效时间不能为空");
        }

        // 校验状态合法性
        if (StringUtils.isNotBlank(entity.getApprovalStatus()) &&
                !"0".equals(entity.getApprovalStatus()) && !"1".equals(entity.getApprovalStatus()) &&
                !"2".equals(entity.getApprovalStatus())) {
            throw new RuntimeException("审批状态只能是0(待审批)、1(已通过)或2(已拒绝)");
        }
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean approveApplication(Long applicationId, String approver, String approvalOpinion) {
        try {
            // 查询调薪申请
            SalaryAdjustmentApplication application = baseMapper.selectById(applicationId);
            if (application == null) {
                return false;
            }

            // 检查申请状态是否为待审批
            if (!"0".equals(application.getApprovalStatus())) {
                return false;
            }

            // 更新审批信息
            application.setApprovalStatus("1"); // 已通过
            application.setApprover(approver);
            application.setApprovalTime(new Date());
            application.setApprovalOpinion(approvalOpinion);

            boolean result = baseMapper.updateById(application) > 0;

            // 如果审批通过成功，则自动更新薪资结构表并触发通知
            if (result) {
                updateSalaryStructureAndNotify(application);
            }

            return result;
        } catch (Exception e) {
            // 记录日志
            log.error("审批调薪申请失败", e);
            throw new RuntimeException("审批调薪申请失败", e);
        }
    }

    /**
     * 审批通过后自动更新薪资结构并触发通知
     *
     * @param application 调薪申请
     */
    private void updateSalaryStructureAndNotify(SalaryAdjustmentApplication application) {
        try {
            // 更新薪资结构表
            updateSalaryStructure(application);

            // 触发通知
            triggerNotification(application);
        } catch (Exception e) {
            // 记录日志
            log.error("更新薪资结构或触发通知失败", e);
            throw new RuntimeException("更新薪资结构或触发通知失败", e);
        }
    }

    /**
     * 更新薪资结构表
     *
     * @param application 调薪申请
     */
    private void updateSalaryStructure(SalaryAdjustmentApplication application) {
        try {
            // 查询员工最新的薪资结构记录
            LambdaQueryWrapper<SalaryStructure> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(SalaryStructure::getEmployeeNo, application.getEmployeeNo());
            queryWrapper.orderByDesc(SalaryStructure::getYearMonth);

            List<SalaryStructure> structures = salaryStructureMapper.selectList(queryWrapper);
            if (!structures.isEmpty()) {
                SalaryStructure latestStructure = structures.get(0);

                // 创建新的薪资结构记录（基于最新记录）
                SalaryStructure newStructure = new SalaryStructure();
                // 复制基础信息
                newStructure.setTenantId(latestStructure.getTenantId());
                newStructure.setEmployeeNo(latestStructure.getEmployeeNo());
                newStructure.setEmployeeName(latestStructure.getEmployeeName());
                newStructure.setBankCardNo(latestStructure.getBankCardNo());
                newStructure.setBankName(latestStructure.getBankName());
                newStructure.setDepartment(latestStructure.getDepartment());

                // 设置新的年月（假设调薪生效时间的年月）
                String yearMonth = String.format("%tY%<tm", application.getEffectiveTime());
                newStructure.setYearMonth(yearMonth);

                // 更新基本工资为新的薪资标准
                newStructure.setBaseSalary(application.getNewSalary());

                // 保持其他字段不变
                newStructure.setJobLevelSalary(latestStructure.getJobLevelSalary());
                newStructure.setPositionSalary(latestStructure.getPositionSalary());
                newStructure.setPerformanceSalary(latestStructure.getPerformanceSalary());
                newStructure.setDutyAllowance(latestStructure.getDutyAllowance());
                newStructure.setShouldAttendanceDays(latestStructure.getShouldAttendanceDays());
                newStructure.setAbsenceDays(latestStructure.getAbsenceDays());
                newStructure.setPaidAttendanceDays(latestStructure.getPaidAttendanceDays());
                newStructure.setAbsenceDeduction(latestStructure.getAbsenceDeduction());
                newStructure.setMealAllowance(latestStructure.getMealAllowance());
                newStructure.setOtherAdjustment(latestStructure.getOtherAdjustment());
                newStructure.setMealDeduction(latestStructure.getMealDeduction());
                newStructure.setGrossSalary(latestStructure.getGrossSalary());
                newStructure.setPensionDeduction(latestStructure.getPensionDeduction());
                newStructure.setUnemploymentDeduction(latestStructure.getUnemploymentDeduction());
                newStructure.setMedicalDeduction(latestStructure.getMedicalDeduction());
                newStructure.setMajorMedicalDeduction(latestStructure.getMajorMedicalDeduction());
                newStructure.setSocialInsurancePersonal(latestStructure.getSocialInsurancePersonal());
                newStructure.setHousingFundPersonal(latestStructure.getHousingFundPersonal());
                newStructure.setSocialHousingTotal(latestStructure.getSocialHousingTotal());
                newStructure.setTaxableSalary(latestStructure.getTaxableSalary());
                newStructure.setPersonalTax(latestStructure.getPersonalTax());
                newStructure.setNetSalary(latestStructure.getNetSalary());
                newStructure.setStatus(latestStructure.getStatus());

                // 插入新的薪资结构记录
                salaryStructureMapper.insert(newStructure);
            }
        } catch (Exception e) {
            // 记录日志
            log.error("更新薪资结构失败", e);
            throw new RuntimeException("更新薪资结构失败", e);
        }
    }

    /**
     * 触发通知
     *
     * @param application 调薪申请
     */
    private void triggerNotification(SalaryAdjustmentApplication application) {
        try {
            // TODO: 集成消息队列+第三方服务实现真实送达
            // 这里暂时打印日志表示触发通知
            log.info("调薪申请已通过，触发通知给员工: {}", application.getEmployeeNo());

            // 可以调用通知服务发送通知
            // notificationService.sendAdjustmentNotification(application);
        } catch (Exception e) {
            // 记录日志
            log.error("触发通知失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean rejectApplication(Long applicationId, String approver, String approvalOpinion) {
        try {
            // 查询调薪申请
            SalaryAdjustmentApplication application = baseMapper.selectById(applicationId);
            if (application == null) {
                return false;
            }

            // 检查申请状态是否为待审批
            if (!"0".equals(application.getApprovalStatus())) {
                return false;
            }

            // 更新审批信息
            application.setApprovalStatus("2"); // 已拒绝
            application.setApprover(approver);
            application.setApprovalTime(new Date());
            application.setApprovalOpinion(approvalOpinion);

            return baseMapper.updateById(application) > 0;
        } catch (Exception e) {
            // 记录日志
            log.error("拒绝调薪申请失败", e);
            throw new RuntimeException("拒绝调薪申请失败", e);
        }
    }
}
